
module Operator(
  input  wire        clk,
  input  wire        rst_n,
  input  wire        clken,

  input  wire [ 4:0] slot,
  input  wire [ 1:0] stage,
  input  wire        rhythm,
  
  input  wire        WF,
  input  wire [ 2:0] FB,

  input  wire        noise,
  input  wire [ 8:0] pgout,
  input  wire [ 6:0] egout,

  output reg  [ 3:0] faddr,
  input  wire [ 9:0] fdata,

  output reg  [ 7:0] opout
);

reg  [8:0] addr;
wire [7:0] data;

SineTable U_SineTable(
    .clk   ( clk   ) ,
    .rst_n ( rst_n ) ,
    .wf    ( WF    ) ,
    .addr  ( addr  ) ,
    .data  ( data  ) 
);

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	opout <= #1 8'b0;
    else if(clken)
	opout <= #1 opout;
    else if(stage==2'd2)
        if({1'b0, egout} + {1'b0,data[6:0]} < 8'h80)
	    opout <= #1 {data[7], (egout + data[6:0])};
        else
	    opout <= #1 {data[7], 7'h7F};
end

reg[10:0] modula;
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	modula <= #1 11'b0;
    else if(clken)
	modula <= #1 modula;
    else if((!rhythm) || ((slot!=5'd14) && (slot!=5'd15) && (slot!=5'd16) && (slot!=5'd17))) begin
	if(!slot[0])
            if(FB==3'b000)
		modula <= #1 11'b0;
	     else
		modula <= #1 {1'b0, fdata[8:0], 1'b0} >> (3'd7 - FB);
        else
		modula <= #1 {fdata[8:0], 2'b00};
    end	
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        addr <= #1  9'b0;
    else if(clken)
	addr <= #1 addr;
    else if(stage == 2'd0)
	if(rhythm && ((slot==5'd14) || (slot==5'd17)))
	    if(noise)
		addr <= #1 9'd127;
	    else
		addr <= #1 9'd383;
	else if(rhythm && (slot == 5'd15))
	    if(pgout[8])
		addr <= #1 9'd128;
	    else
		addr <= #1 9'd383;
	else if(rhythm && (slot == 5'd16))
		addr <= #1 pgout;
        else if(!fdata[9])
		addr <= #1 pgout + modula[8:0];
	else 
		addr <= #1 pgout - modula[8:0];
end

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
	faddr <= #1 10'b0;
    else if(clken)
	faddr <= #1 10'b0;
    else if(stage == 2'd2) begin
	if(slot[0])
	    if(slot[4:1] == 4'd8)
		faddr <= #1 10'b0;
	    else
		faddr <= #1 slot[4:1] + 1'b1;
	else
		faddr <= #1 slot[4:1];
    end
end

endmodule
